﻿using System.Collections.Generic;
using System.Collections.Specialized;
using Wintellect.PowerCollections;

namespace MathMLToCSharp.Entities
{
  /// <summary>
  /// Completely spurious element that MathType 6 insists on generating.
  /// </summary>
  public class Semantics : WithBuildableContents
  {
    internal const string starPrefix = "_star";

    /// <summary>
    /// Functions which need replacement.
    /// </summary>
    internal static readonly List<string> knownFuncts;

    /// <summary>
    /// Symbols and function names that can be replaced.
    /// </summary>
    internal static readonly Dictionary<string, Pair<string, string>> rep;
    /// <summary>
    /// Trig functions which have an inverse, and their inverse values.
    /// </summary>
    internal static StringDictionary inverseTrigs;


    static Semantics()
    {
      rep = new Dictionary<string, Pair<string, string>>
      {
        {"∞", new Pair<string, string>("double.MaxValue", null)},
        {"pi", new Pair<string, string>("pi", "ReplacePiWithMathPI")},
        {"e", new Pair<string, string>("e", null)},
        {"exp", new Pair<string,string>("exp", null)},
        {"*", new Pair<string,string>("star", null)},

         //functions
        {"abs",  new Pair<string, string>("abs(", null)},
        {"sin",  new Pair<string, string>("sin(", null)},
        {"cos",  new Pair<string, string>("cos(", null)},
        {"tan",  new Pair<string, string>("tan(", null)},
        {"sec",  new Pair<string, string>("sec(", null)},
        {"cosec",  new Pair<string, string>("cosec(", null)},
        {"cot",  new Pair<string, string>("cot(", null)},
        {"arcsin",  new Pair<string, string>("arcsin(", null)},
        {"arccos",  new Pair<string, string>("arccos(", null)},
        {"arctan",  new Pair<string, string>("arctan(", null)},
        {"ln",  new Pair<string, string>("ln(", null)},
        {"log",  new Pair<string, string>("log(", null)},
        {"antilog",  new Pair<string, string>("antilog(", null)},
        {"sqrt",  new Pair<string, string>("sqrt(", null)},
        {"sinh",  new Pair<string, string>("sinh(", null)},
        {"cosh",  new Pair<string, string>("cosh(", null)},
        {"tanh",  new Pair<string, string>("tanh(", null)},
        {"arcsinh",  new Pair<string, string>("arcsinh(", null)},
        {"arccosh",  new Pair<string, string>("arccosh(", null)},
        {"arctanh",  new Pair<string, string>("arctanh(", null)}
      };

      inverseTrigs = new StringDictionary
      {
        {"sin", "arcsin"},
        {"cos", "arccos"},
        {"tan", "arctan"},
        {"csc", "arccsc"},
        {"sec", "arcsec"},
        {"cot", "arccot"}
      };

      knownFuncts = new List<string>
      {
         "abs",
         "sin",
         "cos",
         "tan",
         "sec",
         "cosec",
         "cot",
         "arcsin",
         "arccos",
         "arctan",
         "exp",
         "ln",
         "log",
         "antilog",
         "sqrt",
         "sinh",
         "cosh",
         "tanh",
         "arcsinh",
         "arccosh",
         "arctanh"
      };
    }

    public Semantics(IBuildable[] contents) : base(contents) {}

    internal static string postfixForDataType(EquationDataType type)
    {
      switch (type)
      {
        case EquationDataType.Decimal:
          return "M";
        case EquationDataType.Float:
          return "f";
        default:
          return string.Empty;
      }
    }
  }
}